package com.black.cat.jvm.classfile.constantpool;

import com.black.cat.jvm.classfile.ClassReader;
import com.black.cat.jvm.classfile.constantpool.impl.*;
import com.black.cat.jvm.common.CommonValue;

/**
 * @Author blackcat
 * @create 2021/8/12 9:19
 * @version: 1.0
 * @description:创建ConstantInfo 的工厂和ConstantInfo抽象实现
 */
public abstract class BaseConstantInfo implements ConstantInfo {

    protected String value;

    @Override
    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return getTag() + "--------------" + getValue();
    }


//            | 类型                             | 标志(tag 区分类型) | 描述                       |
//            | -------------------------------- | ------------------ | -------------------------- |
//            | CONSTANT_Utf8_info               | 1                  | UTF-8 编码的字符串         |
//            | CONSTANT_Integer_info            | 3                  | 整性字面量                 |
//            | CONSTANT_Float_info              | 4                  | 浮点型字面量               |
//            | CONSTANT_Long_info               | 5                  | 长整型字面量               |
//            | CONSTANT_Double_info             | 6                  | 双精度浮点型字面量         |
//            | CONSTANT_Class_info              | 7                  | 类或则接口的符号引用       |
//            | CONSTANT_String_info             | 8                  | 字符串类型字面量           |
//            | CONSTANT_Fieldref_info           | 9                  | 字段的符号引用             |
//            | CONSTANT_Methodref_info          | 10                 | 类中方法的符号引用         |
//            | CONSTANT_InterfaceMethodref_info | 11                 | 接口中的方法符号引用       |
//            | CONSTANT_NameAndType_info        | 12                 | 字段或者方法的部分符号引用 |
//            | CONSTANT_MethodHandle_info       | 15                 | 表示方法句柄               |
//            | CONSTANT_MethodType_info         | 16                 | 标识方法类型               |
//            | CONSTANT_InvokeDynamic_info      | 18                 | 表示一个动态方法的调用点   |
    // 工厂方法
    public static ConstantInfo createConstantInfo(int tag, ClassReader reader, ConstantPool constantPool) {
        switch (tag) {
            //UTF-8 编码的字符串
            case CommonValue.CONSTANT_POOL_TAG_UTF8:
                return new ConstantInfoUft8(reader);

            // 数字
            case CommonValue.CONSTANT_POOL_TAG_INTEGER:
                return new ConstantInfoInteger(reader);
            case CommonValue.CONSTANT_POOL_TAG_FLOAT:
                return new ConstantInfoFloat(reader);
            case CommonValue.CONSTANT_POOL_TAG_LONG:
                return new ConstantInfoLong(reader);
            case CommonValue.CONSTANT_POOL_TAG_DOUBLE:
                return new ConstantInfoDouble(reader);


            // 以下3个引用UTF8
            case CommonValue.CONSTANT_POOL_TAG_STRING:
                return new ConstantInfoString(constantPool, reader);
            case CommonValue.CONSTANT_POOL_TAG_CLASS:
                return new ConstantInfoClass(constantPool, reader);
            case CommonValue.CONSTANT_POOL_TAG_NAME_AND_TYPE:
                return new ConstantInfoNameAndType(constantPool, reader);

            // 以下3个引用CLASS+NAME_AND_TYPE
            case CommonValue.CONSTANT_POOL_TAG_FIELD_REF:
                return new ConstantInfoFieldref(constantPool, reader);
            case CommonValue.CONSTANT_POOL_TAG_METHOD_REF:
                return new ConstantInfoMethodref(constantPool, reader);
            case CommonValue.CONSTANT_POOL_TAG_INTERFACE_METHOD_REF:
                return new ConstantInterfaceMethodRefInfo(constantPool, reader);

            // 是Java SE 7才添加到class文件中的，目的是支持新增的invokedynamic指令
            case CommonValue.CONSTANT_POOL_TAG_METHOD_HANDLE:
                return new ConstantInfoMethodHandle(constantPool, reader);
            case CommonValue.CONSTANT_POOL_TAG_METHOD_TYPE:
                return new ConstantInfoMethodType(constantPool, reader);
            case CommonValue.CONSTANT_POOL_TAG_INVOKE_DYNAMIC:
                return new ConstantInfoInvokeDynamic(constantPool, reader);

            default:
                throw new ClassFormatError("constant pool tag!");
        }
    }
}
